package org.akomantoso.core.io.util;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.akomantoso.core.data.LiElement;
import org.akomantoso.core.data.Ol;
import org.akomantoso.core.data.P;
import org.akomantoso.core.data.StringItem;
import org.akomantoso.core.data.Ul;
import org.akomantoso.core.io.Input;
import org.akomantoso.core.io.InputConstants;
import org.akomantoso.core.io.util.group.InlineCMGroup;
import org.akomantoso.core.util.MapUtil;

public class LiElementUtil {

	private LiElementUtil() {
	}

	static final Map<String, Instantiator<LiElement>> MAP;

	private static LiElement instantiate(String elementName) {
		final Instantiator<LiElement> instatiator = MAP.get(elementName);
		if (instatiator == null) {
			throw new RuntimeException("Tag [" + elementName + "] not supported for LiElement ?!?");
		}
		return instatiator.instantiate();

	}

	public static void read(Input in, List<LiElement> elements) throws IOException {
		final String localName = in.getLocalName();
		LiElement element = null;
		while (true) {
			in.readNext();
			switch (in.getEventType()) {
			case InputConstants.START_ELEMENT:
				elements.add(element = instantiate(in.getLocalName()));
				element.readExternal(in);
				break;
			case InputConstants.CHARACTERS:
				String tempString = in.readContent();
				if (tempString.trim().length() > 0) {
					elements.add(new StringItem(tempString));
				}
				break;
			case InputConstants.END_ELEMENT:
				if (localName.equals(in.getLocalName())) {
					return;
				}
			}
		}
	}

	static {
		Map<String, Instantiator<LiElement>> temp = new HashMap<String, Instantiator<LiElement>>();

		MapUtil.copy(InlineCMGroup.MAP, temp);

		// p
		temp.put(P.ELEMENT, new Instantiator<LiElement>() {
			public P instantiate() {
				return new P();
			}
		});

		// ol
		temp.put(Ol.ELEMENT, new Instantiator<LiElement>() {
			public Ol instantiate() {
				return new Ol();
			}
		});

		// ul
		temp.put(Ul.ELEMENT, new Instantiator<LiElement>() {
			public Ul instantiate() {
				return new Ul();
			}
		});

		MAP = Collections.unmodifiableMap(temp);
	}

}